// @Desc:
// @CreateTime: 2020/10/8
package user

import (
	"math"
	"net/http"
	"strconv"

	"gitee.com/xuesongtao/gotool/xlog"
	"github.com/gin-gonic/gin"
	"mycrm.com/config"
	. "mycrm.com/controller"
	. "mycrm.com/module"
	"mycrm.com/module/menu"
	"mycrm.com/module/role"
	"mycrm.com/module/user"
	"mycrm.com/utils"
)

// login
func Login(c *gin.Context) {
	var userInfo user.CrmUser
	if err := c.BindJSON(&userInfo); err != nil {
		xlog.Error("c.BindJSON(userInfo) is failed, err: ", err)
		return
	}
	xlog.Infof("sign: %+v", userInfo)
	var hasNum int64 // 大于 0 则有该用户
	resp := Response{
		Status: 1,
		Msg:    "登录成功",
	}
	Db.Model(&user.CrmUser{}).Where("username = ? AND password = ?", userInfo.Username, userInfo.Password).Count(&hasNum)
	if hasNum == 0 { // 登录信息不正确
		resp.Status = 0
		resp.Msg = "用户名或密码错误"
	} else { // 查询是否启用
		var (
			res      user.CrmUser
			resNum   int64 // 用于判断是否有值
			visitUrl string
			roleId   int
		)
		Db.Find(&res, "username = ? AND password = ? AND status = 1", userInfo.Username, userInfo.Password).Count(&resNum)
		xlog.Info("resNum: ", resNum)
		if resNum == 0 {
			resp.Status = 0
			resp.Msg = "请联系管理员启用账号"
		} else { // 获取该用户登录成功的第一个 url
			Db.Model(&user.CrmUser2role{}).Where("user_id = ?", res.ID).Select("role_id").Scan(&roleId)
			Db.Table("crm_role2menu AS r2u").Joins("JOIN crm_menu AS m ON r2u.menu_id = m.id").Where("r2u.role_id = ? AND m.parent_id > 0", roleId).Select("m.url").Limit(1).Scan(&visitUrl)
		}
		loginToken, err := utils.GenerateToken(userInfo.Username, userInfo.Password)
		if err != nil {
			resp.Data = "系统错误, 请联系管理员"
		} else {
			resp.Data = map[string]interface{}{"uid": res.ID, "name": res.Name, "token": loginToken, "token_expire": config.Configs.AuthConf.TokenExpire, "role_id": roleId, "visit_url": visitUrl}
		}
	}
	c.JSON(http.StatusOK, &resp)
}

// register
func Register(c *gin.Context) {
	var userInfo user.CrmUser
	if err := c.BindJSON(&userInfo); err != nil {
		xlog.Error("c.BindJSON(userInfo) is failed, err: ", err)
		return
	}
	xlog.Infof("%s is register", userInfo.Username)
	resp := Response{
		Status: 1,
		Msg:    "注册成功",
	}
	// 先查询用户名是否存在
	var hasNum int64
	Db.Model(&user.CrmUser{}).Where("username = ?", userInfo.Username).Count(&hasNum)
	if hasNum > 0 {
		resp.Status = 0
		resp.Msg = "用户名已存在"
	} else {
		// 将注册的用户的权限都设置为 员工
		userInfo.User2Role = []user.CrmUser2role{{RoleId: userInfo.RoleId}}
		Db.Create(&userInfo)
	}
	c.JSON(200, resp)
}

// user list
func List(c *gin.Context) {
	pageStr := c.Query("cur_page")
	pageNum, _ := strconv.Atoi(pageStr)
	name := c.Query("search_name")
	username := c.Query("search_username")
	statusStr := c.Query("search_status")
	groupId := c.Query("search_groupId")
	statusNum, _ := strconv.Atoi(statusStr)
	tx := Db.Table("crm_user as u").
		Joins("LEFT JOIN crm_user2role as u2r ON u.id = u2r.user_id").
		Joins("LEFT JOIN crm_role as r ON u2r.role_id = r.id").
		Joins("LEFT JOIN crm_usergroup as ug ON u.group_id = ug.id")
	// 姓名查询
	if name != "" {
		tx.Where("u.name = ?", name)
	}
	// 用户名
	if username != "" {
		tx.Where("u.username = ?", username)
	}
	// 状态
	if statusStr != "" {
		tx.Where("u.status = ?", statusNum)
	}
	// 分组 id
	if groupId != "" {
		tx.Where("u.group_id = ?", groupId)
	}
	var (
		pageSize int = 10 // 每页显示
		userInfo []map[string]interface{}
		total    int64 // 总条数
	)
	tx.Count(&total).Select("u.*, r.name as role_name, r.id as role_id, ug.group_name as group_name").Limit(pageSize).Offset((pageNum - 1) * pageSize).Scan(&userInfo)
	// xlog.Info("total: ", total)
	totalPage := int(math.Ceil(float64(total) / float64(pageSize)))
	// xlog.Info("totalPage: ", totalPage)
	// xlog.Info("respUserInfo: ", userInfo)
	resp := &Response{
		Status:      1,
		Data:        &userInfo,
		Total:       int(total),
		CurrentPage: pageNum,
		TotalPage:   totalPage,
	}
	c.JSON(http.StatusOK, resp)
}

// edit user
func Edit(c *gin.Context) {
	var userInfo user.CrmUser
	if err := c.BindJSON(&userInfo); err != nil {
		xlog.Error("c.BindJSON(userInfo) is failed, err: ", err)
		return
	}
	xlog.Infof("%s is edit", userInfo.Username)
	resp := Response{
		Status: 1,
		Msg:    "修改成功",
	}
	if userInfo.ID == 1 {
		resp.Status = 0
		resp.Msg = "管理员不能被修改"
	} else {
		if err := Db.Model(&user.CrmUser{}).Where("id = ?", userInfo.ID).Updates(userInfo).Error; err != nil {
			xlog.Error("Db.Model(&user.CrmUser{}).Updates(userInfo).Error is failed, err: ", err)
			resp.Status = 0
			resp.Msg = "修改失败"
		} else { // 更新成后, 修改 role 关联
			Db.Model(&user.CrmUser2role{}).Where("user_id = ?", userInfo.ID).Update("role_id", userInfo.RoleId)
		}
	}
	c.JSON(http.StatusOK, resp)

}

// user del
func Del(c *gin.Context) {
	delUid := c.Param("delUid")
	// 用于判断该用户是否具有删除条件
	curUserId := c.Param("curUserId")
	xlog.Info("delUid: ", delUid)
	resp := Response{
		Status: 1,
		Msg:    "success",
	}
	var roleIdSlice []uint8
	Db.Table("crm_user2role").Select("role_id").Where("user_id = ?", curUserId).Scan(&roleIdSlice)
	// xlog.Info("roleIdSlice: ", roleIdSlice)
	hasDelAuth := false
	for _, roleId := range roleIdSlice {
		if roleId == 1 { // 1 为管理员权限
			hasDelAuth = true
			break
		}
	}
	if !hasDelAuth {
		resp.Status = 0
		resp.Msg = "你没有删除权限"
	} else {
		Db.Delete(&user.CrmUser{}, delUid)
		// 删除关联数据
		Db.Delete(&user.CrmUser2role{}, "user_id = ?", delUid)
	}
	c.JSON(http.StatusOK, &resp)
}

// 获取角色
func GetRoleInfo(c *gin.Context) {
	var (
		roleInfo []role.Role
	)
	Db.Select("id,name").Find(&roleInfo)
	xlog.Info("resp: ", roleInfo)
	resp := Response{
		Status: 1,
		Data:   roleInfo,
	}
	c.JSON(http.StatusOK, resp)
}

// 根据 uid 判断其该显示的菜单
func ShowMenu(c *gin.Context) {
	uid := c.Param("uid")
	// todo 现在只做了是否显示系统管理

	var roleId int
	resp := Response{
		Status: 1,
	}
	// 管理员 和 最高领导才有
	Db.Model(&user.CrmUser2role{}).Select("role_id").Where("user_id = ?", uid).Scan(&roleId)
	resp.Data = roleId
	c.JSON(http.StatusOK, &resp)

}

// 获取所有设计师
func GetDesginer(c *gin.Context) {
	uid := c.Query("uid")
	resp := &Response{
		Status: 1,
	}
	if uid != "" { // 根据 uid 查询单个人的
		var name string
		Db.Model(&user.CrmUser{}).Where("id = ?", uid).Select("name").Scan(&name)
		resp.Data = name
	} else {
		var allDesginer []map[string]interface{}
		Db.Model(&user.CrmUser{}).Select("id, name").Scan(&allDesginer)
		resp.Data = allDesginer
	}

	c.JSON(http.StatusOK, &resp)
}

// 根据 uid 获取菜单
func GetMenus(c *gin.Context) {
	roleId := c.Param("roleId")
	// 查询所有菜单权限
	var (
		menus []menu.CrmMenu
		resp  []menu.Menus
	)
	Db.Table("crm_role2menu AS r2u").Joins("LEFT JOIN crm_menu AS m ON r2u.menu_id = m.id").Where("r2u.role_id = ?", roleId).Scan(&menus)
	// xlog.Info("menus: ", menus)
	resp = mergeMenu(menus)
	// respJson, _ := json.Marshal(resp)
	// xlog.Info("resp: ", string(respJson))
	c.JSON(http.StatusOK, Response{
		Status: 1,
		Data:   &resp,
	})
}

// 获取菜单
func mergeMenu(menus []menu.CrmMenu) []menu.Menus {
	respMenus := make([]menu.Menus, 0, 10)
	for _, parentNode := range menus {
		if parentNode.ParentId != 0 { // 为根节点
			continue
		}
		curNode := menu.Menus{
			Parent:   menu.CrmMenu{MyBaseModel: MyBaseModel{ID: parentNode.ID}, Name: parentNode.Name, ClassIcon: parentNode.ClassIcon},
			Children: make([]menu.CrmMenu, 0, 5),
		}
		for _, sonNode := range menus {
			if sonNode.ParentId == 0 { // 为根节点
				continue
			}
			if parentNode.ID == sonNode.ParentId {
				children := menu.CrmMenu{
					MyBaseModel: MyBaseModel{ID: sonNode.ID},
					Name:        sonNode.Name,
					Url:         sonNode.Url,
				}
				curNode.Children = append(curNode.Children, children)
			}
		}
		respMenus = append(respMenus, curNode)
	}
	return respMenus
}
